package com.toutiao.cut.impl;

import org.apache.log4j.Logger;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.Serializable;
import java.util.*;

/**
 * Created by wuxian on 16/5/6.
 * 细粒度分词器(后处理)
 */
public class FineCutter implements Serializable {

	private static final long serialVersionUID = 1L;

	private static final Logger log = Logger.getLogger(Combinator.class);

    private Set<String> suffix;
    LanguageModel m;

    public FineCutter(String location, LanguageModel lm) {
        suffix = new HashSet<String>();
        init(location, suffix);
        m = lm;
    }

    private void init(String location, Set<String> set) {
        File file = new File(location);
        Scanner scanner = null;
        String line = null;
        try {
            scanner = new Scanner(file, "UTF-8");
            while (scanner.hasNextLine()) {
                line = scanner.nextLine();
                List<String> ts = Arrays.asList(line.split("\\s"));
                String v = ts.get(0);
                set.add(v);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            log.error(e.getMessage());
            System.exit(1);
        }
    }

    public List<String> process(List<String> ns) {
//		// 这个版本会抽取所有组成成分
//        for (int w = 0; w < ns.size(); w++) {
//            StringBuilder sb = new StringBuilder(ns.get(w));
//            for (int i = ns.get(w).length() - 1; i > 0; i--) {
//                String a = ns.get(w).substring(0, i);
//                String b = ns.get(w).substring(i);
//                if (m.containsKey(a) && m.containsKey(b)) {
//                    if (a.length() > 1) sb.append("|").append(a);
//                    if (b.length() > 1) sb.append("|").append(b);
//                }
//            }
//            ns.set(w, sb.toString());
//        }

        // 这个版本会抽取概率最大的组成方式
        // 对于三字词,利用规则进行拆分
        List<String> ts = new ArrayList<String>(ns.size());
        for (int w = 0; w < ns.size(); w++) {

            ts.add(decompose(ns.get(w)));
        }
        return ts;
    }

    private String decompose(String s) {
        double score = -1000000000;
        int index = -1;
        if (isE(s))
            return s;
        if (s.length() < 3 || s.length() == 3 && !suffix.contains(s.substring(s.length()-1)))
            return s;
        for (int i = s.length() - 1; i > 0; i--) {
            String a = s.substring(0, i);
            String b = s.substring(i);
            if (m.containsKey(a) && m.containsKey(b)) {
                double tmp = m.getTrieValue(a) + m.getTrieValue(b);
                if (tmp > score) {
                    score = tmp;
                    index = i;
                }
            }
        }
        StringBuilder sb = new StringBuilder(s);
        if (index != -1) {
            String a = s.substring(0, index);
            String b = s.substring(index);
            if (a.length() > 1) sb.append("|").append(decompose(a));
            if (b.length() > 1) sb.append("|").append(decompose(b));
        }
        return sb.toString();
    }

    private static final String CT_SINGLE = "._-";
    private boolean isC(char c) {
        int t = Character.getType(c);
        if (t == Character.UPPERCASE_LETTER ||
                t == Character.LOWERCASE_LETTER ||
                t == Character.TITLECASE_LETTER ||
                t == Character.MODIFIER_LETTER ||
                t == Character.DECIMAL_DIGIT_NUMBER ||
                CT_SINGLE.indexOf(c) >= 0)
            return true;

        return false;
    }
    private boolean isE(String s) {
        for (int i = 0; i < s.length(); i++) {
            if (!isC(s.charAt(i)))
                return false;
        }
        return true;
    }
}
